home *** CD-ROM | disk | FTP | other *** search
/ OpenGL Superbible (2nd Edition) / OpenGL SuperBible e2.iso / tools / GLUT-3.7 / PROGS / ADVANCED / hello2rts.c < prev    next >
Encoding:
C/C++ Source or Header  |  1998-08-12  |  12.6 KB  |  551 lines

  1.  
  2. /* Copyright (c) Mark J. Kilgard, 1997, 1998.  */
  3.  
  4. /* This program is freely distributable without licensing fees and is
  5.    provided without guarantee or warrantee expressed or implied.  This
  6.    program is -not- in the public domain. */
  7.  
  8. /* This code demonstrates use of the OpenGL Real-time Shadowing (RTS)
  9.    routines.  The program renders two objects with two light sources in a
  10.    scene with several other walls and curved surfaces.  Objects cast shadows
  11.    on the walls and curved surfaces as well as each other.  The shadowing
  12.    objects spin.  See the rts.c and  rtshadow.h source code for more details. */
  13.  
  14. #include <stdio.h>
  15. #include <string.h>
  16. #include <math.h>
  17. #include <stdlib.h>
  18. #include <GL/glut.h>
  19.  
  20. #ifdef GLU_VERSION_1_2
  21.  
  22. #include "rtshadow.h"
  23.  
  24. /* Some <math.h> files do not define M_PI... */
  25. #ifndef M_PI
  26. #define M_PI 3.14159265358979323846
  27. #endif
  28.  
  29. enum {
  30.   X, Y, Z
  31. };
  32.  
  33. enum {
  34.   DL_NONE, DL_TORUS, DL_CUBE, DL_DOUBLE_TORUS, DL_SPHERE
  35. };
  36.  
  37. enum {
  38.   M_TORUS, M_CUBE, M_DOUBLE_TORUS, M_NORMAL_VIEW, M_LIGHT1_VIEW, M_LIGHT2_VIEW,
  39.   M_START_MOTION, M_ROTATING,
  40.   M_TWO_BIT_STENCIL, M_ALL_STENCIL,
  41.   M_RENDER_SILHOUETTE,
  42.   M_ENABLE_STENCIL_HACK, M_DISABLE_STENCIL_HACK
  43. };
  44.  
  45. #define OBJECT_1  0x8000
  46. #define OBJECT_2  0x4000
  47.  
  48. int lightView = M_NORMAL_VIEW;
  49. int rotate1 = 1, rotate2 = 1;
  50.  
  51. RTSscene *scene;
  52. RTSlight *light;
  53. RTSlight *light2;
  54. RTSobject *object, *object2;
  55.  
  56. GLfloat eyePos[3] =
  57. {0.0, 0.0, 10.0};
  58. GLfloat lightPos[4] =
  59. {-3.9, 5.0, 1.0, 1.0};
  60. GLfloat lightPos2[4] =
  61. {4.0, 5.0, 0.0, 1.0};
  62. GLfloat objectPos[3] =
  63. {-1.0, 1.0, 0.0};
  64. GLfloat objectPos2[3] =
  65. {2.0, -2.0, 0.0};
  66.  
  67. GLfloat pink[4] =
  68. {0.75, 0.5, 0.5, 1.0};
  69. GLfloat greeny[4] =
  70. {0.5, 0.75, 0.5, 1.0};
  71.  
  72. int shape1 = M_TORUS, shape2 = M_CUBE;
  73. int renderSilhouette1, renderSilhouette2;
  74.  
  75. GLfloat angle1 = 75.0;
  76. GLfloat angle2 = 75.0;
  77. GLfloat viewAngle = 0.0;
  78. int moving, begin;
  79.  
  80. void
  81. renderBasicObject(int shape)
  82. {
  83.   switch (shape) {
  84.   case M_TORUS:
  85.     glCallList(DL_TORUS);
  86.     break;
  87.   case M_CUBE:
  88.     glCallList(DL_CUBE);
  89.     break;
  90.   case M_DOUBLE_TORUS:
  91.     glCallList(DL_DOUBLE_TORUS);
  92.     glutSolidTorus(0.2, 0.8, 10, 10);
  93.     break;
  94.   }
  95. }
  96.  
  97. /* ARGSUSED */
  98. void
  99. renderObject(void *data)
  100. {
  101.   glPushMatrix();
  102.   glTranslatef(objectPos[X], objectPos[Y], objectPos[Z]);
  103.   glRotatef(angle1, 1.0, 1.2, 0.0);
  104.   renderBasicObject(shape1);
  105.   glPopMatrix();
  106. }
  107.  
  108. /* ARGSUSED */
  109. void
  110. renderObject2(void *data)
  111. {
  112.   glPushMatrix();
  113.   glTranslatef(objectPos2[X], objectPos2[Y], objectPos2[Z]);
  114.   glRotatef(-angle2, 1.3, 0.0, 1.0);
  115.   renderBasicObject(shape2);
  116.   glPopMatrix();
  117. }
  118.  
  119. /* ARGSUSED1 */
  120. void
  121. renderScene(GLenum castingLight, void *sceneData, RTSscene * scene)
  122. {
  123.   glMatrixMode(GL_PROJECTION);
  124.   glLoadIdentity();
  125.   gluPerspective(70.0, 1.0, 0.5, 30.0);
  126.  
  127.   glMatrixMode(GL_MODELVIEW);
  128.   glLoadIdentity();
  129.   switch (lightView) {
  130.   case M_NORMAL_VIEW:
  131.     gluLookAt(eyePos[X], eyePos[Y], eyePos[Z],
  132.       objectPos[X], objectPos[Y], objectPos[Z],
  133.       0.0, 1.0, 0.0);
  134.     break;
  135.   case M_LIGHT1_VIEW:
  136.     gluLookAt(lightPos[X], lightPos[Y], lightPos[Z],
  137.       objectPos[X], objectPos[Y], objectPos[Z],
  138.       0.0, 1.0, 0.0);
  139.     break;
  140.   case M_LIGHT2_VIEW:
  141.     gluLookAt(lightPos2[X], lightPos2[Y], lightPos2[Z],
  142.       objectPos[X], objectPos[Y], objectPos[Z],
  143.       0.0, 1.0, 0.0);
  144.     break;
  145.   }
  146.   glLightfv(GL_LIGHT0, GL_POSITION, lightPos);
  147.   glLightfv(GL_LIGHT1, GL_POSITION, lightPos2);
  148.  
  149.   glEnable(GL_NORMALIZE);
  150.   glPushMatrix();
  151.   glTranslatef(0.0, 8.0, -5.0);
  152.   glScalef(3.0, 3.0, 3.0);
  153.   glCallList(DL_SPHERE);
  154.   glPopMatrix();
  155.   glDisable(GL_NORMALIZE);
  156.  
  157.   glPushMatrix();
  158.   glTranslatef(-5.0, 0.0, 0.0);
  159.   glCallList(DL_SPHERE);
  160.   glPopMatrix();
  161.  
  162.   glBegin(GL_QUADS);
  163.   glNormal3f(0.0, 0.0, 1.0);
  164.   glVertex3f(-7.5, -7.5, -7.0);
  165.   glVertex3f(7.5, -7.5, -7.0);
  166.   glVertex3f(7.5, 7.5, -7.0);
  167.   glVertex3f(-7.5, 7.5, -7.0);
  168.  
  169.   glNormal3f(-1.0, 0.0, 0.0);
  170.   glVertex3f(5.0, -5.0, -5.0);
  171.   glVertex3f(5.0, -5.0, 5.0);
  172.   glVertex3f(5.0, 5.0, 5.0);
  173.   glVertex3f(5.0, 5.0, -5.0);
  174.  
  175.   glNormal3f(0.0, 1.0, 0.0);
  176.   glVertex3f(-5.0, -5.0, -5.0);
  177.   glVertex3f(-5.0, -5.0, 5.0);
  178.   glVertex3f(5.0, -5.0, 5.0);
  179.   glVertex3f(5.0, -5.0, -5.0);
  180.  
  181.   glEnd();
  182.  
  183.   if (castingLight == GL_NONE) {
  184.     /* Rendering that is not affected by lighting should be drawn only once.
  185.        The time to render it is when no light is casting. */
  186.     glDisable(GL_LIGHTING);
  187.  
  188.     glColor3fv(pink);
  189.     glPushMatrix();
  190.     glTranslatef(lightPos[X], lightPos[Y], lightPos[Z]);
  191.     glutSolidSphere(0.3, 8, 8);
  192.     glPopMatrix();
  193.  
  194.     glColor3fv(greeny);
  195.     glPushMatrix();
  196.     glTranslatef(lightPos2[X], lightPos2[Y], lightPos2[Z]);
  197.     glutSolidSphere(0.3, 8, 8);
  198.     glPopMatrix();
  199.  
  200.     glEnable(GL_LIGHTING);
  201.   }
  202.   renderObject(NULL);
  203.   renderObject2(NULL);
  204. }
  205.  
  206. void
  207. display(void)
  208. {
  209.   glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
  210.   rtsRenderScene(scene, RTS_USE_SHADOWS);
  211.   if (renderSilhouette1) {
  212.     glColor3f(0.0, 1.0, 0.0);
  213.     rtsRenderSilhouette(scene, light, object);
  214.     glColor3f(0.0, 0.0, 1.0);
  215.     rtsRenderSilhouette(scene, light2, object);
  216.   }
  217.   if (renderSilhouette2) {
  218.     glColor3f(1.0, 0.0, 0.0);
  219.     rtsRenderSilhouette(scene, light, object2);
  220.     glColor3f(1.0, 1.0, 0.0);
  221.     rtsRenderSilhouette(scene, light2, object2);
  222.   }
  223.   glutSwapBuffers();
  224. }
  225.  
  226. void
  227. idle(void)
  228. {
  229.   if (rotate1) {
  230.     angle1 += 10;
  231.     rtsUpdateObjectShape(object);
  232.   }
  233.   if (rotate2) {
  234.     angle2 += 10;
  235.     rtsUpdateObjectShape(object2);
  236.   }
  237.   glutPostRedisplay();
  238. }
  239.  
  240. /* ARGSUSED1 */
  241. void
  242. special(int c, int x, int y)
  243. {
  244.   switch (c) {
  245.   case GLUT_KEY_UP:
  246.     lightPos[Y] += 0.5;
  247.     rtsUpdateLightPos(light, lightPos);
  248.     break;
  249.   case GLUT_KEY_DOWN:
  250.     lightPos[Y] -= 0.5;
  251.     rtsUpdateLightPos(light, lightPos);
  252.     break;
  253.   case GLUT_KEY_RIGHT:
  254.     lightPos[X] += 0.5;
  255.     rtsUpdateLightPos(light, lightPos);
  256.     break;
  257.   case GLUT_KEY_LEFT:
  258.     lightPos[X] -= 0.5;
  259.     rtsUpdateLightPos(light, lightPos);
  260.     break;
  261.   case GLUT_KEY_PAGE_UP:
  262.     lightPos[Z] += 0.5;
  263.     rtsUpdateLightPos(light, lightPos);
  264.     break;
  265.   case GLUT_KEY_PAGE_DOWN:
  266.     lightPos[Z] -= 0.5;
  267.     rtsUpdateLightPos(light, lightPos);
  268.     break;
  269.   case GLUT_KEY_HOME:
  270.     angle1 += 15;
  271.     angle2 += 15;
  272.     rtsUpdateObjectShape(object);
  273.     rtsUpdateObjectShape(object2);
  274.     break;
  275.   case GLUT_KEY_END:
  276.     angle1 -= 15;
  277.     angle2 -= 15;
  278.     rtsUpdateObjectShape(object);
  279.     rtsUpdateObjectShape(object2);
  280.     break;
  281.   case GLUT_KEY_F1:
  282.     lightView = !lightView;
  283.     break;
  284.   }
  285.   glutPostRedisplay();
  286. }
  287.  
  288. /* ARGSUSED1 */
  289. void
  290. keyboard(unsigned char c, int x, int y)
  291. {
  292.   switch (c) {
  293.   case 27:
  294.     exit(0);
  295.     /* NOTREACHED */
  296.     break;
  297.   case ' ':
  298.     if (rotate1 || rotate2) {
  299.       glutIdleFunc(NULL);
  300.       rotate1 = 0;
  301.       rotate2 = 0;
  302.     } else {
  303.       glutIdleFunc(idle);
  304.       rotate1 = 1;
  305.       rotate2 = 1;
  306.     }
  307.     break;
  308.   }
  309. }
  310.  
  311. void
  312. updateIdleCallback(void)
  313. {
  314.   if (rotate1 || rotate2) {
  315.     glutIdleFunc(idle);
  316.   } else {
  317.     glutIdleFunc(NULL);
  318.   }
  319. }
  320.  
  321. void
  322. visible(int vis)
  323. {
  324.   if (vis == GLUT_VISIBLE)
  325.     updateIdleCallback();
  326.   else
  327.     glutIdleFunc(NULL);
  328. }
  329.  
  330. void
  331. menuHandler(int value)
  332. {
  333.   switch (value) {
  334.   case OBJECT_1 | M_TORUS:
  335.   case OBJECT_1 | M_CUBE:
  336.   case OBJECT_1 | M_DOUBLE_TORUS:
  337.     shape1 = value & ~OBJECT_1;
  338.     rtsUpdateObjectShape(object);
  339.     glutPostRedisplay();
  340.     break;
  341.   case OBJECT_2 | M_TORUS:
  342.   case OBJECT_2 | M_CUBE:
  343.   case OBJECT_2 | M_DOUBLE_TORUS:
  344.     shape2 = value & ~OBJECT_2;
  345.     rtsUpdateObjectShape(object2);
  346.     glutPostRedisplay();
  347.     break;
  348.   case M_NORMAL_VIEW:
  349.   case M_LIGHT1_VIEW:
  350.   case M_LIGHT2_VIEW:
  351.     lightView = value;
  352.     glutPostRedisplay();
  353.     break;
  354.   case M_START_MOTION:
  355.     rotate1 = 1;
  356.     rotate2 = 1;
  357.     glutIdleFunc(idle);
  358.     break;
  359.   case OBJECT_1 | M_ROTATING:
  360.     rotate1 = !rotate1;
  361.     updateIdleCallback();
  362.     break;
  363.   case OBJECT_2 | M_ROTATING:
  364.     rotate2 = !rotate2;
  365.     updateIdleCallback();
  366.     break;
  367.   case M_ALL_STENCIL:
  368.     rtsUpdateUsableStencilBits(scene, ~0);
  369.     glutPostRedisplay();
  370.     break;
  371.   case M_TWO_BIT_STENCIL:
  372.     rtsUpdateUsableStencilBits(scene, 0x3);
  373.     glutPostRedisplay();
  374.     break;
  375.   case OBJECT_1 | M_RENDER_SILHOUETTE:
  376.     renderSilhouette1 = !renderSilhouette1;
  377.     glutPostRedisplay();
  378.     break;
  379.   case OBJECT_2 | M_RENDER_SILHOUETTE:
  380.     renderSilhouette2 = !renderSilhouette2;
  381.     glutPostRedisplay();
  382.     break;
  383.   case M_ENABLE_STENCIL_HACK:
  384.     rtsStencilRenderingInvariantHack(scene, GL_TRUE);
  385.     glutPostRedisplay();
  386.     break;
  387.   case M_DISABLE_STENCIL_HACK:
  388.     rtsStencilRenderingInvariantHack(scene, GL_FALSE);
  389.     glutPostRedisplay();
  390.     break;
  391.   }
  392. }
  393.  
  394. void
  395. initMenu(void)
  396. {
  397.   glutCreateMenu(menuHandler);
  398.  
  399.   glutAddMenuEntry("1 Torus", OBJECT_1 | M_TORUS);
  400.   glutAddMenuEntry("1 Cube", OBJECT_1 | M_CUBE);
  401.   glutAddMenuEntry("1 Double torus", OBJECT_1 | M_DOUBLE_TORUS);
  402.  
  403.   glutAddMenuEntry("2 Torus", OBJECT_2 | M_TORUS);
  404.   glutAddMenuEntry("2 Cube", OBJECT_2 | M_CUBE);
  405.   glutAddMenuEntry("2 Double torus", OBJECT_2 | M_DOUBLE_TORUS);
  406.  
  407.   glutAddMenuEntry("Normal view", M_NORMAL_VIEW);
  408.   glutAddMenuEntry("View from light 1", M_LIGHT1_VIEW);
  409.   glutAddMenuEntry("View from light 2", M_LIGHT2_VIEW);
  410.  
  411.   glutAddMenuEntry("Start motion", M_START_MOTION);
  412.   glutAddMenuEntry("1 Toggle rotating", OBJECT_1 | M_ROTATING);
  413.   glutAddMenuEntry("2 Toggle rotating", OBJECT_2 | M_ROTATING);
  414.  
  415.   glutAddMenuEntry("Use all stencil", M_ALL_STENCIL);
  416.   glutAddMenuEntry("Use only 2 bits stencil", M_TWO_BIT_STENCIL);
  417.  
  418.   glutAddMenuEntry("1 Toggle silhouette", OBJECT_1 | M_RENDER_SILHOUETTE);
  419.   glutAddMenuEntry("2 Toggle silhouette", OBJECT_2 | M_RENDER_SILHOUETTE);
  420.  
  421.   glutAddMenuEntry("Enable stencil hack", M_ENABLE_STENCIL_HACK);
  422.   glutAddMenuEntry("Disable stencil hack", M_DISABLE_STENCIL_HACK);
  423.  
  424.   glutAttachMenu(GLUT_RIGHT_BUTTON);
  425. }
  426.  
  427. /* ARGSUSED2 */
  428. void
  429. mouse(int button, int state, int x, int y)
  430. {
  431.   if (button == GLUT_LEFT_BUTTON && state == GLUT_DOWN) {
  432.     moving = 1;
  433.     begin = x;
  434.   }
  435.   if (button == GLUT_LEFT_BUTTON && state == GLUT_UP) {
  436.     moving = 0;
  437.   }
  438. }
  439.  
  440. /* ARGSUSED1 */
  441. void
  442. motion(int x, int y)
  443. {
  444.   if (moving) {
  445.     viewAngle = viewAngle + (x - begin);
  446.     eyePos[X] = sin(viewAngle * M_PI / 180.0) * 10.0;
  447.     eyePos[Z] = cos(viewAngle * M_PI / 180.0) * 10.0;
  448.     begin = x;
  449.     glutPostRedisplay();
  450.   }
  451. }
  452.  
  453. /* XXX RIVA 128 board vendors may change their GL_VENDOR
  454.    and GL_RENDERER strings. */
  455. int
  456. detectRiva128hardware(void)
  457. {
  458.   const char *vendor, *renderer;
  459.  
  460.   vendor = glGetString(GL_VENDOR);
  461.   renderer = glGetString(GL_RENDERER);
  462.   if (strcmp("NVIDIA Corporation", vendor)) {
  463.     return 0;
  464.   }
  465.   if (strncmp("RIVA 128", renderer, 8)) {
  466.     return 0;
  467.   }
  468.   return 1;
  469. }
  470.  
  471. int
  472. main(int argc, char **argv)
  473. {
  474.   glutInitDisplayString("stencil>=2 rgb double depth samples");
  475.   glutInit(&argc, argv);
  476.  
  477.   glutCreateWindow("Hello to Real Time Shadows");
  478.   glutDisplayFunc(display);
  479.   glutSpecialFunc(special);
  480.   glutKeyboardFunc(keyboard);
  481.   glutVisibilityFunc(visible);
  482.   glutMouseFunc(mouse);
  483.   glutMotionFunc(motion);
  484.  
  485.   /* 0xffffffff means "use as much stencil as is available". */
  486.   scene = rtsCreateScene(eyePos, 0xffffffff, renderScene, NULL);
  487.  
  488.   glLightfv(GL_LIGHT0, GL_POSITION, lightPos);
  489.   glLightfv(GL_LIGHT0, GL_DIFFUSE, pink);
  490.   light = rtsCreateLight(GL_LIGHT0, lightPos, 1000.0);
  491.   glLightfv(GL_LIGHT1, GL_POSITION, lightPos2);
  492.   glLightfv(GL_LIGHT1, GL_DIFFUSE, greeny);
  493.   light2 = rtsCreateLight(GL_LIGHT1, lightPos2, 1000.0);
  494.  
  495.   object = rtsCreateObject(objectPos, 1.0, renderObject, NULL, 100);
  496.   object2 = rtsCreateObject(objectPos2, 1.0, renderObject2, NULL, 100);
  497.  
  498.   rtsAddLightToScene(scene, light);
  499.   rtsAddObjectToLight(light, object);
  500.   rtsAddObjectToLight(light, object2);
  501.  
  502.   rtsAddLightToScene(scene, light2);
  503.   rtsAddObjectToLight(light2, object);
  504.   rtsAddObjectToLight(light2, object2);
  505.  
  506.   if (detectRiva128hardware()) {
  507.     /* RIVA 128 and RIVA 128 ZX lack hardware stencil
  508.        support and the hardware rasterization path
  509.        (non-stenciled) and the software rasterization
  510.        path (with stenciling enabled) do not meet the
  511.        invariants. */
  512.     rtsStencilRenderingInvariantHack(scene, GL_TRUE);
  513.   }
  514.  
  515.   glEnable(GL_CULL_FACE);
  516.   glEnable(GL_DEPTH_TEST);
  517.  
  518.   initMenu();
  519.  
  520.   glNewList(DL_TORUS, GL_COMPILE);
  521.   glutSolidTorus(0.2, 0.8, 10, 10);
  522.   glEndList();
  523.  
  524.   glNewList(DL_CUBE, GL_COMPILE);
  525.   glutSolidCube(1.0);
  526.   glEndList();
  527.  
  528.   glNewList(DL_DOUBLE_TORUS, GL_COMPILE);
  529.   glCallList(DL_TORUS);
  530.   glRotatef(90.0, 0.0, 1.0, 0.0);
  531.   glCallList(DL_TORUS);
  532.   glRotatef(-90.0, 0.0, 1.0, 0.0);
  533.   glEndList();
  534.  
  535.   glNewList(DL_SPHERE, GL_COMPILE);
  536.   glutSolidSphere(1.5, 20, 20);
  537.   glEndList();
  538.  
  539.   glutMainLoop();
  540.   return 0;             /* ANSI C requires main to return int. */
  541. }
  542.  
  543. #else
  544. int main(int argc, char** argv)
  545. {
  546.   fprintf(stderr, "This program requires the new tesselator API in GLU 1.2.\n");
  547.   fprintf(stderr, "Your GLU library does not support this new interface, sorry.\n");
  548.   return 0;
  549. }
  550. #endif  /* GLU_VERSION_1_2 */
  551.